import numpy as np
import matplotlib.pyplot as plt

X = np.linspace(-np.pi, 0)
T = (np.cos(X - np.pi) + 1) / -2 + 1
n_data = len(T)
print("x=", X)
print("n_data = ", n_data)


# 正向传播
def forward(x, w, b):
    u = x * w + b
    y = 1 / (1 + np.exp(-u))
    return y


# 反向传播
def backward(x, y, t):
    delta = (y - t) * (1 - y) * y
    grad_w = x * delta
    grad_b = delta
    return grad_w, grad_b


def show_output(X, Y, T, epoch):
    plt.plot(X, T, linestyle='dashed')
    plt.scatter(X, Y, marker="*")

    plt.xlabel("x", size=14)
    plt.ylabel("y", size=14)
    plt.grid()
    plt.show()
    print("Epoch:", epoch)
    print("Error:", 1 / 2 * np.sum(Y - T) ** 2)


# consts
eta = 0.0005
epoch = 100000

w = 0.2
b = 0.2

for i in range(epoch):
    if i < 1:
        Y = forward(x=X, w=w, b=b)
        show_output(X, Y, T, i)

    idx_rand = np.arange(n_data)
    np.random.shuffle(idx_rand)

    for j in idx_rand:
        x = X[j]
        t = T[j]

        y = forward(x=x, w=w, b=b)
        grand_w, grand_b = backward(x=x, y=y, t=t)
        w -= grand_w * eta
        b -= grand_b * eta

Y = forward(X, w, b)
show_output(X, Y, T, epoch)

